package vn.edu.tdt.it.domain;

import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import vn.edu.tdt.it.common.OWLConst;
import vn.edu.tdt.it.entity.Category;
import vn.edu.tdt.it.entity.MyProperty;
import vn.edu.tdt.it.entity.Page;

import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;

public class BuildOntologyFinal {
	public static final String SOURCE = ":";
	public static final String URI_OWL = "http://it.tdt.edu.vn/entity";
	public static final String URI_REL = "http://it.tdt.edu.vn/relation";
	public static OntModel owlModel;
	public static final String MAIN_CATEGORY = "Khoa_học_tự_nhiên";
	public static final int ID = 1179;
	public static long count = 0;
	public static long countPage = 0;
	public static long totalTime;
	public static List<MyQueue> listCheck;
	public static Hashtable<Integer, Integer> table;
	public static Map<String, Property> owlProperties;

	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
		listCheck = new LinkedList<MyQueue>();
		StaticConnection.DB_URL = "jdbc:mysql://localhost/wiki?useUnicode=true&characterEncoding=UTF-8";
		table = new Hashtable<Integer, Integer>();
		owlModel = ModelFactory.createOntologyModel();
		/*
		 * owlModel.read(
		 * "file:///C:/Users/nbpla_000/MyProjects/LuanVan/ontology.xml");
		 */
		/*
		 * System.out.println("Read Total: " +
		 * owlModel.listClasses().toList().size());
		 */
		owlProperties = new HashMap<String, Property>();
		// Tạo danh sách Properties
		File propFile = new File("input/properties.txt");
		Map<String, Object> mpProp = PropertyMapBuilder.buildProp(propFile);
		Map<String, String> mpStr = (Map<String, String>) mpProp
				.get(OWLConst.MP_PROPERTY);
		for (String s : (List<String>) mpProp.get(OWLConst.LST_PROPERTY)) {
			owlProperties.put(s,
					owlModel.getProperty(URI_REL + SOURCE + mpStr.get(s)));
		}
		// Chạy
		Category khoahoctunhien = new Category(ID, MAIN_CATEGORY);
		totalTime = System.currentTimeMillis();
		addSubClass(khoahoctunhien);
		System.out.println("Total time: "
				+ (System.currentTimeMillis() - totalTime) + "\n");
		// Ghi file
		FileWriter out = new FileWriter(new File("ontologiii.xml"));
		owlModel.write(out, "RDF/XML");
		out.close();
	}

	private static void addSubClass(Category category) throws Exception {
		System.out.println("[INFO] Processing: " + category.getName()
				+ "  Total page: " + countPage);

		if (count % 20 == 0 && count != 0) {
			count++;
			FileWriter out = new FileWriter(new File("ontologiii.xml"));
			owlModel.write(out, "RDF/XML");
			out.close();
			System.err.println("[INFO] Đã ghi file với " + count
					+ " categories. Số page: " + countPage
					+ " Tổng thời gian: "
					+ (System.currentTimeMillis() - totalTime));
		}

		OntClass mainClass;

		if (owlModel.getOntClass(URI_OWL + SOURCE + category.getName()) != null
				&& !owlModel.getOntClass(URI_OWL + SOURCE + category.getName())
						.listInstances().hasNext()
				|| owlModel.getOntClass(URI_OWL + SOURCE + category.getName()) == null) {
			count++;
			mainClass = owlModel.getOntClass(URI_OWL + SOURCE
					+ category.getName());
			if(mainClass==null) {
				mainClass = owlModel.createClass(URI_OWL + SOURCE
						+ category.getName());
				mainClass.setComment(category.nonNomalized, "vi");
			}
			for (Page p : category.getPages()) {
				long time = System.currentTimeMillis();
				countPage++;
				Individual ind = owlModel.createIndividual(
						URI_OWL + SOURCE + p.getName(), mainClass);
				ind.setComment(p.nonNomalized, "vi");
				for (Page eq : p.getEquivalent()) {
					Individual eqv = owlModel.createIndividual(URI_OWL + SOURCE
							+ eq.getName(), mainClass);
					eqv.addSameAs(ind);
					eqv.setComment(eq.nonNomalized, "vi");
				}
				/*
				 * for (MyProperty prop : p.getProperties()) {
				 * 
				 * Individual clss = owlModel.createIndividual(
				 * prop.getDomain(), null); clss.setComment(prop.nonNomalized,
				 * "vi"); ind.addProperty(owlProperties.get(prop.getName()),
				 * clss);
				 * 
				 * }
				 */
				System.out.println("[INFO] Processing page: " + p.getName()
						+ "  --  " + (System.currentTimeMillis() - time));

			}
			for (Category cat : category.getSubCategories()) {
				if (cat == null
						|| listCheck.contains(new MyQueue(category.getId(), cat
								.getId()))) {
					continue;
				}
				if (listCheck.size() >= 20) {
					listCheck.remove(0);
				}
				listCheck.add(new MyQueue(category.getId(), cat.getId()));
				OntClass subClass = owlModel.createClass(URI_OWL + SOURCE
						+ cat.getName());
				subClass.setComment(cat.nonNomalized, "vi");
				mainClass.addSubClass(subClass);
			}
		} else {
			System.out.println("[INFO] Bỏ qua: " + category.getName());
			mainClass = owlModel.createClass(URI_OWL + SOURCE
					+ category.getName());
			mainClass.setComment(category.nonNomalized, "vi");
		}

		List<Category> categ = new ArrayList<Category>();
		categ.addAll(category.getSubCategories());
		category.setSubCategories(null);
		category = null;
		while (categ.size() > 0) {
			Category cat = categ.get(0);
			if (cat != null && !table.containsKey(cat.getId())) {
				table.put(cat.getId(), 0);
				addSubClass(cat);
			}
			categ.remove(0);
		}

	}

}
